<?php

use Carbon\Carbon as Carbon;

class ChartController extends BaseController {

  const STANDARD = 1;
  const GROUPED  = 2;
  const MERGED   = 3;
  const TIMELINE = 4;

  public function timeline($username) {
    $method = self::TIMELINE;
    $user   = Redditor::where('username', '=', $username)->first();
    if ($user) {
      $comments = $user->comments()->orderBy('start', 'ASC')->get();

      $grouped = array();

      foreach ($comments as $c) {
        $start = new Carbon;
        $end = new Carbon;

        // group by day of the week:
        $dotw = Carbon::createFromFormat('Y-m-d H:i:s', $c->end);
        $day           = intval($dotw->format('w'));
        $grouped[$day] = isset($grouped[$day]) ? $grouped[$day] : array();

        // create start datetime:
        $e1 = explode(' ',$c->start);
        $e1 = explode(':', $e1[1]);
        $start->modify($this->_days[$day]);
        $start->setTime($e1[0], $e1[1], $e1[2]);

        // create end datetime
        $e2 = explode(' ',$c->start);
        $e2 = explode(':', $e2[1]);
        $end->modify($this->_days[$day]);
        $end->setTime($e2[0], $e2[1], $e2[2]);

//        echo 'Start: ' . $start->toRFC1123String().'<br>';
//        echo 'End: ' . $end->toRFC1123String().'<br>';

        //$c->start        = Carbon::createFromFormat('w H:i:s', $day . ' ' . $c->start);
        //$c->end          = Carbon::createFromFormat('w H:i:s', $day . ' ' . $c->end);
        // add to smaller thingie
        $grouped[$day][] = array('start' => $start, 'end'   => $end);
      }
    }
    ksort($grouped);


    // so far each day may have up to a hundred time entries, which is a bit much
    // we aren't cutting it down yet, but we should.
    // process:
//    $days  = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Tuesday', 'Friday', 'Saturday');
//    $index = 0;
    switch ($method) {
      case self::STANDARD:
        $data = $this->_standardProcessing($grouped);
        break;
      case self::GROUPED;
        break;
      case self::MERGED;
        $data = $this->_mergedProcessing($grouped);
        break;
      case self::TIMELINE:
        $data = $this->_timelineProcessing($grouped);
        break;
    }

    return Response::json($data);
  }

  private function _timelineProcessing($grouped) {
    $data  = array(
        'cols' => array(
            array(
                'id'    => 'day',
                'label' => 'Day of the week',
                'type'  => 'string',
                'p'     => array('role' => 'domain')
            ),
            array(
                'id'    => 'start',
                'label' => 'Start',
                'type'  => 'date',
                'p'     => array('role' => 'data')),
            array(
                'id'    => 'end',
                'label' => 'End',
                'type'  => 'date',
                'p'     => array('role' => 'data')),
        ),
        'rows' => array()
    );
    $index = 0;
    foreach ($grouped as $dayNumber => $comments) {
      foreach ($comments as $c) {
        $span = false;// ($c['start'] > $c['end']);
        if (!$span) {
          $startHour                         = intval($c['start']->format('H'));
          $startMinute                       = intval($c['start']->format('i'));
          $startSecond                       = intval($c['start']->format('s'));
          $endHour                           = intval($c['end']->format('H'));
          $endMinute                         = intval($c['end']->format('i'));
          $endSecond                         = intval($c['end']->format('s'));
          $data['rows'][$index]['c'][0]['v'] = $this->_days[$dayNumber]; //$c['start']->format('l j M');// $this->_days[$dayNumber];
          $data['rows'][$index]['c'][1]['v'] = 'Date(0,0,0,' . $startHour . ',' . $startMinute . ',' . $startSecond . ')';
          $data['rows'][$index]['c'][2]['v'] = 'Date(0,0,0,' . $endHour . ',' . $endMinute . ',' . $endSecond . ')';
          $index++;
        }
      }
    }

    return $data;
  }

  private function _standardProcessing($grouped) {
    $result = array();
    // loop over each day:
    foreach ($grouped as $dayNumber => $comments) {
      echo 'Now at ' . $this->_days[$dayNumber] . '<br>';
      // create objects for hourly-loop:
      $current  = new Carbon($this->_days[$dayNumber]);
      $tomorrow = clone $current;
      $tomorrow->addDay();

      // loop over each hour:
      while ($current <= $tomorrow) {
        // set the end time for this hour:
        $endCurrent                = clone $current;
        $endCurrent->addHour();
        $hour                      = $current->format('H:i');
        $result[$dayNumber][$hour] = isset($result[$dayNumber][$hour]) ? $result[$dayNumber][$hour] : 0;

        // loop over todays comments and see if they fit here:
        foreach ($comments as $i => $comment) {

          // reset the comment's date:
          $start = new Carbon($this->_days[$dayNumber]);
          $start->setTime(intval($comment['start']->format('H')), intval($comment['start']->format('i')), intval($comment['start']->format('s')));
          $end   = new Carbon($this->_days[$dayNumber]);
          $end->setTime(intval($comment['end']->format('H')), intval($comment['end']->format('i')), intval($comment['end']->format('s')));
          unset($grouped[$dayNumber][$i]);

          // check if it fits in this hour:
          if (
                  (($start >= $current) && ($end <= $endCurrent)) || // valt er helemaal in.
                  (($start >= $current && $start <= $endCurrent)) || // from valt er in.
                  (($end >= $current && $end <= $endCurrent)) // end valt er in
          // to valt binnen
          ) {
            $result[$dayNumber][$hour]++;
          }
        }

        $current->addHour();
      }
    }
    var_dump($result);
    return array();
  }

  private function _mergedProcessing($grouped) {


    $result = array();
    foreach ($grouped as $dayNumber => $comments) {
      $result[$dayNumber] = isset($result[$dayNumber]) ? $result[$dayNumber] : array();
      $current            = new Carbon($this->_days[$dayNumber]);
      $tomorrow           = clone $current;
      $tomorrow->addDay();

      while ($current <= $tomorrow) {
        $endCurrent                 = clone $current;
        $endCurrent->addMinutes(15);
        $index                      = $current->format('H:i:s');
        $result[$dayNumber][$index] = isset($result[$dayNumber][$index]) ? $result[$dayNumber][$index] : 0;
        foreach ($comments as $i => $comment) {
          $to   = new Carbon($this->_days[$dayNumber]);
          $to->setTime(intval($comment['to']->format('H')), intval($comment['to']->format('i')), intval($comment['to']->format('s')));
          $from = new Carbon($this->_days[$dayNumber]);
          $from->setTime(intval($comment['from']->format('H')), intval($comment['from']->format('i')), intval($comment['from']->format('s')));
          if (
                  (($from >= $current) && ($to <= $endCurrent)) || // valt er helemaal in.
                  (($from >= $current && $from <= $endCurrent)) || // from valt er in.
                  (($to >= $current && $to <= $endCurrent)) // end valt er in
          // to valt binnen
          ) {
            $result[$dayNumber][$index]++;
            unset($comments[$i]);
          }
        }
        $current->addMinutes(15);
      }
    }
    $final = $result[$dayNumber];
    $max   = max($final);


    $data  = array(
        'cols' => array(
            array(
                'id'    => 'timeofday',
                'label' => 'Time of day',
                'type'  => 'date',
                'p'     => array('role' => 'domain')
            ),
            array(
                'id'    => 'posts',
                'label' => 'Posts',
                'type'  => 'number',
                'p'     => array('role' => 'data')),
        ),
        'rows' => array()
    );
    $index = 0;
    foreach ($final as $timestring => $posts) {
      $time = explode(':', $timestring);
      if ($posts > 0) {
        $data['rows'][$index]['c'][0]['v'] = 'Date(0,0,0,' . $time[0] . ',' . $time[1] . ',' . $time[2] . ')';
        $data['rows'][$index]['c'][1]['v'] = $posts / $this->_weeks;
        $index++;
      }
    }
    return $data;
  }

  //    echo '<pre>';
//    echo json_encode($data, JSON_PRETTY_PRINT);
//    print_r($data);
//    print_r($grouped);
//    echo '</pre>';
  //    foreach ($grouped as $dayNumber => $comments) {
//      //$data['rows'][$index]['c'][0]['v'] = $chartdate->format('j F');
//
//      foreach ($comments as $i => $comment) {
//        //echo 'at '.$i."<br>";
//
//        $to   = new Carbon($days[$dayNumber]);
//        $to->setTime(intval($comment['to']->format('H')), intval($comment['to']->format('i')), intval($comment['to']->format('s')));
//        $from = new Carbon($days[$dayNumber]);
//        $from->setTime(intval($comment['from']->format('H')), intval($comment['from']->format('i')), intval($comment['from']->format('s')));
//
//        if ($group) {
//          if ($i == 0) {
//            $currentStart = clone $from;
//            $currentEnd   = clone $to;
//          }
//
//          if (
//                  ($from > $currentStart && $from < $currentEnd && $to > $currentEnd) ||
//                  ($from < $currentStart && $to > $currentEnd)
//          ) {
//            $currentStart = clone $from;
//            $currentEnd   = clone $to;
//            //echo $i . ': option 1<br>';
//          } else if ($from > $currentStart && $to < $currentEnd) {
//            // continue
//            //echo $i . ': option 2<br>';
//          } else if (
//                  ($from > $currentEnd && $to > $currentEnd) ||
//                  ($from < $currentStart && $to < $currentStart)
//          ) { // safety option really
//            //echo $i . ': option 3<br>';
//            // add then clone:
//            $span = ($currentStart > $currentEnd);
//            if (!$span) {
//              //echo $i . ': added!<br>';
//              $startHour                         = intval($currentStart->format('H'));
//              $startMinute                       = intval($currentStart->format('i'));
//              $startSecond                       = intval($currentStart->format('s'));
//              $endHour                           = intval($currentEnd->format('H'));
//              $endMinute                         = intval($currentEnd->format('i'));
//              $endSecond                         = intval($currentEnd->format('s'));
//              $data['rows'][$index]['c'][0]['v'] = $days[$dayNumber];
//              $data['rows'][$index]['c'][1]['v'] = 'Date(0,0,0,' . $startHour . ',' . $startMinute . ',' . $startSecond . ')';
//              $data['rows'][$index]['c'][2]['v'] = 'Date(0,0,0,' . $endHour . ',' . $endMinute . ',' . $endSecond . ')';
//              $index++;
//              $currentStart                      = clone $from;
//              $currentEnd                        = clone $to;
//            }
//          } else {
//            // echo 'NONE<br>';
//          }
//        } else {
//          // always add a new row:
//          $span        = $from > $to;
//          $startHour   = intval($from->format('H'));
//          $startMinute = intval($from->format('i'));
//          $startSecond = intval($from->format('s'));
//          $endHour     = intval($to->format('H'));
//          $endMinute   = intval($to->format('i'));
//          $endSecond   = intval($to->format('s'));
//          if (!$span) {
//            $data['rows'][$index]['c'][0]['v'] = $days[$dayNumber];
//            $data['rows'][$index]['c'][1]['v'] = 'Date(0,0,0,' . $startHour . ',' . $startMinute . ',' . $startSecond . ')';
//            $data['rows'][$index]['c'][2]['v'] = 'Date(0,0,0,' . $endHour . ',' . $endMinute . ',' . $endSecond . ')';
//            $index++;
//          }
//        }
//
//        // prevent overnighters.
//        $span  = ($from > $to);
//        $reset = true;
//        if (!$span) {
//          $startHour   = intval($from->format('H'));
//          $startMinute = intval($from->format('i'));
//          $startSecond = intval($from->format('s'));
//          $endHour     = intval($to->format('H'));
//          $endMinute   = intval($to->format('i'));
//          $endSecond   = intval($to->format('s'));
//
//          $data['rows'][$index]['c'][0]['v'] = $days[$dayNumber];
//          $data['rows'][$index]['c'][1]['v'] = 'Date(0,0,0,' . $startHour . ',' . $startMinute . ',' . $startSecond . ')';
//          $data['rows'][$index]['c'][2]['v'] = 'Date(0,0,0,' . $endHour . ',' . $endMinute . ',' . $endSecond . ')';
//          $index++;
//        }
//      }
//    }
}

function t(Carbon $time) {
  return $time->toRFC822String();
}